package com.rengwuxian.coursecoroutines._4_flow

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.EmptyCoroutineContext

/**
 * 自定义Flow操作符
 * 自定义Flow操作符 / flow() / channelFlow()
 *
 * 用一个现成的Flow对象，来创建另一个Flow对象，它肯定是Flow的扩展函数。加入范型。返回值是Flow。
 * 1.先用flow或者channelFlow创建一个什么都不修改的Flow出来
 * 2.把扩展函数左边的Flow对象和右边的Flow对象结合起来，把数据转发到下游去
 *   当右边被外部调用collect时，整个flow大括号开始运转，故在运转的第一时间进行左边Flow对象的collect
 *   将上下游数据连接起来。
 * fun <T> Flow<T>.customOperator(): Flow<T> = flow {
 *   collect {
 *     emit(it)
 *     emit(it)
 *   }
 * }
 */
fun main() = runBlocking<Unit> {
  val scope = CoroutineScope(EmptyCoroutineContext)
  val flow1 = flowOf(1, 2, 3)
  scope.launch {
    flow1.customOperator().collect { println("1: $it") }
    flow1.double().collect { println("2: $it") }
  }
  delay(10000)
}

fun <T> Flow<T>.customOperator(): Flow<T> = flow {
  collect {
    emit(it)
    emit(it)
  }
}

fun Flow<Int>.double(): Flow<Int> = channelFlow {
  collect {
    send(it * 2)
  }
}